#ifndef _MM_H_
#define _MM_H_
#define CFCONS_ID_VALUE       0
#define CFSYMBOL_ID_VALUE     1
#define CFINTEGER_ID_VALUE    2
#define CFFLOAT_ID_VALUE      3
#define CFVECTOR_ID_VALUE     4
#define CFCHARACTER_ID_VALUE  5
/* #define CFSTRELEMENT_ID_VALUE 6 */
#define CFSTRING_ID_VALUE     6

#define CFINTEGER_TYPE   0
#define CFCONS_TYPE      1
#define CFSYMBOL_TYPE    2
#define CFFLOAT_TYPE     3
#define CFVECTOR_TYPE    4
#define CFCHARACTER_TYPE 5
#define CFSTRING_TYPE    6
#define CFCALLER_TYPE    7

#define MAX_PACKAGE_SIZE 128

#define NTYPES 7
#define PAGESIZE  128  /* TODO: MUST CHANGE THIS TO A PROPER PAGESIZE */
extern char * XTypeNames[];
#define _TYPE(x) XTypeNames[x] 

typedef struct XPackage {
	char * name;
	struct XPackage * next;
	struct XSymbol * hashTable [MAX_PACKAGE_SIZE];
}CFPackage;

typedef struct XCons{
  char type;
  void * car;
  void * cdr;
} CFCons;

typedef struct XSymbol {
  char type;
	unsigned isDefined :1;
	unsigned isGlobal : 1;
	char * string;
	void * value;
	void * hashvalue;
	CFPackage * package;
} CFSymbol;

typedef struct XInteger {
	char type;
  int number;
} CFInteger;

typedef struct XFloat {
  char type;
  double number;
} CFDouble;

typedef struct XVector {
  char type;
  int size;
  void * cells;
} CFVector;

typedef struct XCharacter {
  char type;
  char character;
} CFCharacter;

typedef struct XString {
  char type;
  int length;
  char * string;
} CFString;

typedef struct XCaller {
  char type;
  int length;
  void * sexpr;
} CFCaller;
/*
typedef struct XCondition{
  char type;
  void * symbolName;
  void * listOfVars;
}CFCondition;

typdef struct XHandler {
  char type;
  void * whereTo;
  void * catches;
}
*/

CFCons * MMCons (void * car, void * cdr);
CFSymbol * MMSymbol(char * string, char * package);
CFInteger * MMInteger(int i);
CFDouble * MMDouble(double d);
CFVector * MMVector(int size);
CFCharacter * MMChar(char string);
CFString * MMString(char * string);
void MMInit(void);
void MMDelete(void);
CFPackage * MMPackage (char * name);
CFSymbol * MMSymbolNotSeperated (char * string);
#define MMInt MMInteger
#define MMGetType(x) 0x0f & ((CFInteger *) x)->type
#define MMCar(x) ((CFCons *) x)->car
#define MMCdr(x) ((CFCons *) x)->cdr
#define MMWord(m) MMSymbol (m)
#define MMIsType(x,y) (MMGetType(x)) == y
#define MMIntegerValue(x) ((CFInteger *) x)->number
#define MMDoubleValue(x) ((CFDouble *) x)->number
#define MMVectorSize(x) ((CFVector *) x)->size
#define MMVectorCell(x) ((CFVector *) x)->cells
#define MMCharValue(x) ((CFCharacter *) x)->character
#define MMSymbolName(x) ((CFSymbol *) x)->string
#define MMSymbolPackage(x) ((CFSymbol *) x)->package
#define MMStringString(x) (char *) ((CFString *) x)->string
#define MMStringLength(x)  ((CFString *) x)->length
#define MMPackageName(x) x->name
#define MMCallerLength(x) ((CFCaller *) x)->length
#define MMCallerSExpr(x) ((CFCaller *) x)->sexpr

extern CFSymbol * mm_alloc_t;
extern CFSymbol * mm_alloc_nil;

#define MMNil() mm_alloc_nil
#define MMT() mm_alloc_t

CFCaller * MMCaller(void * sexpr);
#endif /*_MM_H_*/
